SQL 처리를 위한 다양한 확장 기능

표준/네이티브 매개변수 바인딩과다양한 확장 기능을 알아봅니다.

QCN

dbclient 모듈의 주요 기능

  • 개발자가 직접 SQL 쿼리를 작성하고 관리할 수 있도록 합니다.
  • 복잡하거나 최적화가 필요한 쿼리, 혹은 데이터베이스 특정 기능을 활용해야 하는 경우에 큰 장점이 됩니다.
  • 조건문(if), 반복문(foreach)과 같이 동적 SQL 지원해서 다양한 조건에 따라 유연하게 쿼리를 구성합니다.

ORM(Object-Relational Mapping) 프레임워크가 자동으로 SQL을 생성하는 것과 대비되는 부분입니다.

QCN

SQL 매개변수 바인딩

HandStack은 데이터베이스가 제공하는 네이티브 매개변수 바인딩을 기본으로 사용합니다. 이는 SQL Injection 공격을 방어하는 가장 기본적인 방법입니다.

  • @ 접두사: 표준적인 SQL 매개변수 표기법
  • : 접두사: Oracle 등에서 사용하는 표기법
  • ? : 순서 기반 매개변수 표기법
SELECT UserID, UserName
FROM   Users
WHERE  UserID = @UserID;
  • 위 예제에서 @UserID는 외부에서 전달된 UserID 값으로 안전하게 치환됩니다.
QCN

문자열 변수 치환: ${...}#{...}

동적 테이블명, 컬럼명 또는 LIKE 구문 등 매개변수 바인딩이 불가능한 경우 문자열 치환을 사용합니다.

  • ${...}: 따옴표 없이 변수 값을 그대로 치환합니다.
  • #{...}: 변수 값을 문자열로 간주하여 따옴표로 감싸 치환합니다.
SELECT UserID, UserName
FROM   Users
WHERE  UserName LIKE '%' + #{KEYWORD} + '%'
SELECT UserID, UserName, Email
FROM   ${TABLE_NAME}
WHERE  Status = 'Active'
QCN

로그인 세션 매개변수 사용

사용자의 세션 정보(예: 사용자 ID, 부서 코드)를 SQL 쿼리에서 직접 사용할 수 있습니다. 세션 정보는 로그인 과정에서 업무에 따라 부여합니다.

  • 세션 변수는 $ 접두사를 사용합니다.
  • 컨트롤러나 비즈니스 로직에서 세션 값을 매번 전달할 필요가 없어 코드가 간결해집니다.
<param id="@$CONCURRENTCOMPANYNO" type="String" length="-1" value="NULL" />
<param id="@$CONCURRENTUSERNO" type="String" length="-1" value="NULL" />
WHERE DOF.COMPANY_NO IN (${$CONCURRENTCOMPANYNO})
  AND DOF.EMPLOYEE_NO IN (${$CONCURRENTUSERNO})
QCN

전처리 변수 추가: <pretreatment>

SQL 실행 전에 특정 쿼리를 먼저 실행하고, 그 결과를 다음 쿼리의 매개변수로 사용할 수 있습니다.

  • resultType="Row": 단일 행 결과를 반환하여 각 컬럼을 변수로 사용합니다.
  • resultType="List": 목록 값을 반환하여 지정된 반복 변수명으로 사용합니다.
<pretreatment resultType="Row">
  SELECT MinorCode AS ProcessStatus, MinorName AS ProcessStatusName
  FROM   CommonCode
  WHERE  MajorCode = 'STATUS' AND MinorCode = @StatusCode
</pretreatment>

  UPDATE Orders SET Status = @ProcessStatus, StatusName = @ProcessStatusName
  WHERE  OrderID = @OrderID
QCN

치환 변수 추가: <bind>

기존 변수들을 조합하거나 가공하여 새로운 변수를 만들어 SQL 내에서 사용할 수 있습니다.

  • 복잡한 표현식을 XML 내에서 처리하여 SQL을 더 간결하게 유지할 수 있습니다.
<bind name="SearchStart" value="StartDate + ' 00:00:00'" />
<bind name="SearchEnd" value="EndDate + ' 23:59:59'" />

  SELECT *
  FROM   EventLogs
  WHERE  EventTime BETWEEN @SearchStart AND @SearchEnd
QCN

동적 쿼리: <if> 조건문

조건에 따라 SQL 구문을 동적으로 추가하거나 변경할 수 있습니다. 검색 조건이 다양한 경우에 매우 유용합니다.

  • test 속성에 JavaScript와 유사한 조건식을 사용합니다.
  SELECT * FROM Products
  WHERE 1 = 1
  <if test="(Keyword != '')">
    AND ProductName LIKE '%' + #{Keyword} + '%'
  </if>
  <if test="(CategoryID > 0)">
    AND CategoryID = @CategoryID
  </if>
QCN

동적 쿼리: <foreach> 반복문

배열이나 리스트 형태의 매개변수를 처리할 때 사용합니다. IN 절을 동적으로 생성하는 데 효과적입니다.

  • collection: 반복할 대상 매개변수 (배열)
  • item: 각 반복에서의 현재 요소 변수명
  • open, close, separator: 반복문의 시작, 끝, 구분자 문자열
  SELECT *
  FROM   Users
  WHERE  UserID IN
  <foreach collection="UserIDs" item="id" open="(" close=")" separator=",">
    @id
  </foreach>
QCN

<param> 초기값 설정하기 (1/2)

매개변수에 대한 초기값을 설정할 때 특정 규칙에 따라 값을 설정할 수 있습니다.

  • <param value="1234">: KEYWORD 매개변수가 요청에 없을 경우 기본값을 설정합니다.
  • NULL 은 매개변수가 요청에 없을 경우 무시합니다.
<statement>
  <param id="@UserID" type="String" length="255" value="NULL" />
</statement>
QCN

<param> 초기값 설정하기 (1/2)

매개변수에 대한 초기값을 설정할 때 특정 키워드를 사용하여 dbclient 모듈에서 부여하는 프로그램 값을 설정할 수 있습니다.

  • "@SUID": sequentialIdGenerator.NewId().ToString("N");
  • "@GUID": Guid.NewGuid();
  • "@NOW": DateTime.Now;
  • "@UTCNOW": DateTime.UtcNow;
  • "@TRUE": true;
  • "@FALSE": false;
  • "@DBNULL": DBNull.Value;
<statement>
  <param id="@UserID" type="String" length="255" value="@SUID" />
</statement>
QCN

<param> 변환값 설정하기

매개변수에 대한 초기값을 설정하거나, 특정 규칙에 따라 값을 변환하는 30개 이상의 키워드를 제공합니다.

  • "@FOREACH": apple,banana,cherry 값을 <foreach> 에 사용
  • "@LOWER": Value.ToLower();
  • "@UPPER": Value.ToUpper();
  • "@STRING2DATETIME|format": DateTime.TryParse(format);
  • "@DATETIME2STRING|format": DateTime.ToString(format);
<statement>
  <param id="@TransformRoles" type="String" length="100" value="NULL" transform="@FOREACH" />
</statement>

더 많은 변환 키워드는 dbclient/DataClient/QueryDataClient.cs 에서 TransformValue 메서드 참조

QCN

핸즈온: 쿼리 테스트 및 XML 작성

  • 쿼리 도구 에서 쿼리 테스트

    • SQL Server Management Studio, DBeaver 클라이언트 도구를 엽니다.
    • 업무 SQL 쿼리를 작성하고 실행하며 원하는 결과가 나오는지 테스트합니다.
    • 동적 조건이 필요한 부분은 주석으로 표기하며 여러 케이스를 테스트합니다.
  • HandStack XML 쿼리로 변환

    • 테스트가 완료된 SQL을 dbclient의 XML 파일로 옮깁니다.
    • 동적으로 처리했던 부분을 <if>, <foreach> 등의 태그를 사용하여 변경합니다.
    • 매개변수는 @ 표기법으로 바꾸고, 필요한 경우 <bind>, <param> 등을 추가하여 쿼리를 완성합니다.
QCN

요약 정리 및 Q&A

Mybatis의 장점과 데이터베이스 중심의 업무 처리 노하우를 활용하는 HandStack이 약속하는 개발 생산성입니다.

  • 안전한 매개변수 바인딩을 기본으로 제공합니다.
  • 동적 SQL을 XML 내에서 선언적으로 쉽게 작성할 수 있습니다.
  • SQL과 비즈니스 로직의 관심사를 분리하여 유지보수성을 높입니다.
  • 복잡한 데이터 처리 로직을 SQL에 집중시켜 애플리케이션 코드를 단순하게 유지합니다.
QCN